package org.tinygame.herostory.cmdhandler;

import com.google.protobuf.GeneratedMessageV3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinygame.herostory.util.PackageUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author anan
 * @create 2022-05-02 0:44
 */
public final class CmdHandlerFactory {
    static final private Map<Class<?>, ICmdHandler<? extends GeneratedMessageV3>> _handlerMap = new HashMap<>();

    static final private Logger LOGGER = LoggerFactory.getLogger(CmdHandlerFactory.class);

    private CmdHandlerFactory(){}

    static public void init(){

        LOGGER.info("=== 完成命令与处理器的关联 ===");

        final String packageName = CmdHandlerFactory.class.getPackage().getName();

        Set<Class<?>> clazzSet = PackageUtil.listSubClazz(packageName, true, ICmdHandler.class);

        for(Class<?> handlerClazz : clazzSet){
            if (null == handlerClazz ||
                    0 != (handlerClazz.getModifiers() & Modifier.ABSTRACT)){
                continue;
            }

            Method[] methodArray = handlerClazz.getDeclaredMethods();
            Class<?> cmdClazz = null;
            for(Method currMethod : methodArray){
                if(currMethod.isBridge()){
                    //LOGGER.info("11111111111111" + currMethod.getName() + "            " + handlerClazz.getName());
                    continue;  
                }
                if(null == currMethod ||
                        !currMethod.getName().equals("handle")){
                    continue;
                }
                Class<?>[] paramTypeArray = currMethod.getParameterTypes();
                if(paramTypeArray.length < 2 ||
                        paramTypeArray[1] == GeneratedMessageV3.class||
                        !GeneratedMessageV3.class.isAssignableFrom(paramTypeArray[1])){
                    continue;
                }
                cmdClazz = paramTypeArray[1];
                break;

            }
            if(null == cmdClazz) continue;
            try {
                ICmdHandler<?> newHandler = (ICmdHandler<?>) handlerClazz.newInstance();
                LOGGER.info("{} <==> {}",
                        cmdClazz.getName(),
                        handlerClazz.getName());
                _handlerMap.put(cmdClazz, newHandler);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }

        }

        /*_handlerMap.put(GameMsgProtocol.UserEntryCmd.class, new UserEntryCmdHandler());
        _handlerMap.put(GameMsgProtocol.WhoElseIsHereCmd.class, new WhoElseisHereCmdHandler());
        _handlerMap.put(GameMsgProtocol.UserMoveToCmd.class, new UserMoveToCmdHandler());*/
    }

    static public ICmdHandler<? extends GeneratedMessageV3> create(Class<?> msgClazz) {
        if (null == msgClazz) {
            return null;
        }

        return _handlerMap.get(msgClazz);
    }

}
